package com.itic.im.redis;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.itic.im.core.ImManager;
import com.itic.im.redis.listener.RedisSubMessageListener;
import com.itic.im.redis.template.RedisImTemplateImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Redis IM管理器
 *
 * @author wanli.yang
 * @version 1.0
 * @date 2022/1/12 12:43
 */
@SuppressWarnings("deprecation")
public class RedisImManager {
    private static final Logger logger = LoggerFactory.getLogger(RedisImManager.class);

    /**
     * room - channel
     */
    public static Map<String, String> channelMap = new ConcurrentHashMap<String, String>();
    /**
     * channel - listener
     */
    public static Map<String, MessageListener> channelListener = new ConcurrentHashMap<>();

    /**
     * 创建频道
     * @param roomId
     * @param channel
     * @return void
     */
    public static void createChannel(String roomId, String channel) {
        channelMap.put(roomId, channel);
    }

    /**
     * 创建频道
     * @param roomIds
     * @param channel
     * @return void
     */
    public static void createChannel(List<String> roomIds, String channel) {
        if(CollectionUtil.isNotEmpty(roomIds)) {
            roomIds.stream().forEach(e -> {
                RedisImManager.createChannel(e, channel);
            });
        }
    }

    /**
     * 获取频道
     * @param roomId
     * @return void
     */
    public static String getChannel(String roomId) {
        if(StrUtil.isEmpty(channelMap.get(roomId))) {
            synchronized (RedisImTemplateImpl.class) {
                if(StrUtil.isEmpty(channelMap.get(roomId))) {
                    // 如果是默认房间，就启用默认频道
                    String channel = roomId.equals(ImManager.getConfig().getRoomId())?ImManager.getConfig().getChannel(): RandomUtil.randomString(10);
                    createChannel(roomId, channel);
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    logger.warn("IM实时通讯Gate系统，房间{}监听频道{}成功.", roomId, channel);
                }
            }
        }
        if(null == getChannelListeners(channelMap.get(roomId))) {
            // 没有指定监听器，就用默认的
            setChannelListeners(channelMap.get(roomId), SpringUtil.getBean(RedisSubMessageListener.class));
        }
        return channelMap.get(roomId);
    }

    /**
     * 移除频道
     * @param roomId
     * @return void
     */
    public static void removeChannel(String roomId) {
        channelMap.remove(roomId);
    }

    /**
     * 给频道绑定监听器
     * @param channel
     * @param listener
     * @return void
     */
    public static void setChannelListeners(String channel, MessageListener listener) {
        MessageListener messageListener = channelListener.get(channel);
        RedisMessageListenerContainer rmls = SpringUtil.getBean(RedisMessageListenerContainer.class);
        if(null != messageListener) {
            // 如果之前存在则覆盖
            rmls.removeMessageListener(messageListener, new PatternTopic(channel));
            messageListener = null;
        }
        channelListener.put(channel, listener);

        rmls.addMessageListener(listener, new PatternTopic(channel));
    }

    public static MessageListener getChannelListeners(String channel) {
        return channelListener.get(channel);
    }

    public static void removeChannelListeners(String channel) {
        MessageListener messageListener = channelListener.get(channel);
        RedisMessageListenerContainer rmls = SpringUtil.getBean(RedisMessageListenerContainer.class);
        if(null != messageListener) {
            // 如果之前存在则覆盖
            rmls.removeMessageListener(messageListener, new PatternTopic(channel));
            messageListener = null;
        }
        channelListener.remove(channel);
    }
}
